#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/of_irq.h> 
#include <linux/irq.h>
#include <linux/platform_device.h> 
#include <linux/miscdevice.h>

#define MISLED_MINOR	144
#define MISLED_NAME		"misled"

struct misled_st
{
	int led_gpio;
	struct device_node *node;
};
static struct misled_st misled;

static int misled_open(struct inode *inode, struct file *flip)
{
	flip->private_data = &misled;

	return 0;
}

static ssize_t misled_write(struct file *flip, const char __user *buf, size_t cnt, loff_t *off_t)
{
	u8 stat;
	int ret =0;
	struct misled_st *me = (struct misled_st *)flip->private_data;

	ret = copy_from_user(&stat, buf, 1);
	if(ret <0)
	{
		printk("copy_from_user error\r\n");
		return -EINVAL;
	}

	if(stat ==0)
	{
		gpio_set_value(me->led_gpio,1);
	}
	else if(stat ==1)
	{
		gpio_set_value(me->led_gpio,0);
	}
	else
		printk("unknown\r\n");

	return 0;
}

static const struct file_operations misled_ops = 
{
	.owner 	= THIS_MODULE,
	.open 	= misled_open,
	.write 	= misled_write,
};

static struct miscdevice  misled_st = 
{
	.minor = MISLED_MINOR,
	.name  = MISLED_NAME,
	.fops  = &misled_ops,
};

static int misled_probe(struct platform_device *pdev)
{
	int ret =0;

	misled.node = of_find_node_by_path("/soc/i2c@1C27000/touchscreen@38");
	if(misled.node ==NULL)
	{
		printk("of_find_node_by_path error\r\n");
		return -EINVAL;
	}

	misled.led_gpio = of_get_named_gpio(misled.node, "reset-gpios", 0);
	if(misled.led_gpio <0)
	{
		printk("of_get_named_gpio error\r\n");
		return -EINVAL;
	}

	ret = gpio_request(misled.led_gpio, MISLED_NAME);
	if(ret <0)
	{
		printk("gpio_request error\r\n");
		return -EINVAL;
	}

	ret = gpio_direction_output(misled.led_gpio, 1);
	if(ret <0)
	{
		printk("gpio_direction_output error\r\n");
		return -EINVAL;
	}

	ret = misc_register(&misled_st);
	if(ret <0)
	{
		printk("misc_register error\r\n");
		return -EINVAL;
	}

	printk("misled_probe sucess\r\n");

	return 0;
}

static int misled_remove(struct platform_device *pdev)
{
	gpio_set_value(misled.led_gpio, 1);
	gpio_free(misled.led_gpio);

	misc_deregister(&misled_st);

	printk("misled_remove sucess\r\n");
	return 0;
}

static const struct of_device_id misled_of_match[] = 
{
	{.compatible = "my-keys"},
	{}
};

static struct platform_driver miscled_driver = 
{
	.driver = {
		.name = "f1c200s-led",
		.of_match_table = misled_of_match,
	},
	.probe 	= misled_probe,
	.remove = misled_remove,
};

static int __init miscled_init(void)
{
	return platform_driver_register(&miscled_driver);
}

static void __exit miscled_exit(void)
{
	platform_driver_unregister(&miscled_driver);
}

module_init(miscled_init);
module_exit(miscled_exit);
MODULE_AUTHOR("jtb");
MODULE_LICENSE("GPL");

